// 版权归Go作者所有。版权所有。
// 此源代码的使用受BSD样式的约束
// 可以在许可证文件中找到的许可证。

// go:构建达尔文| | |蜻蜓| | freebsd | | linux | | netbsd | openbsd
// +构建达尔文蜻蜓freebsd linux netbsd openbsd

package typecheck

import (
	"os"
	"reflect"
	"syscall"
	"unsafe"
)

// TODO（mdempsky）：还有更高级别的抽象吗
// 对进口很有效？

// mapFile返回文件中从起始位置开始的长度字节
// 将偏移量指定为字符串。
func mapFile(f *os.File, offset, length int64) (string, error) {
	// POSIX mmap：“该实现可能要求off是一个
	// 页面大小的倍数。”
	x := offset & int64(os.Getpagesize()-1)
	offset -= x
	length += x

	buf, err := syscall.Mmap(int(f.Fd()), offset, int(length), syscall.PROT_READ, syscall.MAP_SHARED)
	keepAlive(f)
	if err != nil {
		return "", err
	}

	buf = buf[x:]
	pSlice := (*reflect.SliceHeader)(unsafe.Pointer(&buf))

	var res string
	pString := (*reflect.StringHeader)(unsafe.Pointer(&res))

	pString.Data = pSlice.Data
	pString.Len = pSlice.Len

	return res, nil
}

// keepAlive是runtime.keepAlive的重新实现，它不是
// 添加到Go 1.7，而我们需要使用Go 1.4进行编译。
var keepAlive = func(interface{}) {}
